package com.lzc.springcloud.user.config;

import com.lzc.springcloud.user.application.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationFailureHandler;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class WebSecruityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .logout()
                .logoutUrl("/logout").permitAll().and()
                .authorizeRequests().antMatchers("/**/login.html", "/", "/index", "/**/logout", "/**/gologin.html").permitAll().and()
                .httpBasic().and()
                .formLogin()
                .loginPage("/identity/login.html").loginProcessingUrl("/identity/login.html")
                .successForwardUrl("/identity/gologin2").failureForwardUrl("/identity/login.html").and()
                .csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    /**
     * 去除spring-security默认的权限前缀ROLE_
     * @return
     */
    @Bean
    protected RoleVoter roleVoter() {
        RoleVoter voter = new RoleVoter();
        voter.setRolePrefix("");
        return voter;
    }

    /**
     * authenticatedVoter是为了支持IS_AUTHENTICATED这种认证
     * authenticatedVoter提供的3种认证，分别是：
     * IS_AUTHENTICATED_ANONYMOUSLY 允许匿名用户进入
     * IS_AUTHENTICATED_FULLY 允许登录用户进入
     * IS_AUTHENTICATED_REMEMBERED 允许登录用户和rememberMe用户进入
     * @return
     */
    @Bean
    protected AuthenticatedVoter authenticatedVoter() {
        return new AuthenticatedVoter();
    }

    /**
     * 决策管理器
     * Spring提供了3个决策管理器：
     * AffirmativeBased 一票通过，只要有一个投票器通过就允许访问
     * ConsensusBased 有一半以上投票器通过才允许访问资源
     * UnanimousBased 所有投票器都通过才允许访问
     * @return
     */
    @Bean
    protected AffirmativeBased accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> voters = new ArrayList<>();
        voters.add(roleVoter());
        voters.add(authenticatedVoter());
        return new AffirmativeBased(voters);
    }

    /**
     * 跟踪活跃的session,统计在线人数,显示在线用户.
     * @return
     */
    @Bean
    public SessionRegistry sessionRegistry(){
        return new SessionRegistryImpl();
    }

    //    /**
//     * 允许用户同时在线数，有一个maximumSessions属性，默认是1。通过sessionRegistry判断用户数是否已经超过了最大允许数，若超过了，那么就让最近一个的session过期（让上一个用户强制下线）
//     * @return
//     */
//    @Bean
//    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
//        return new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
//    }
}
